﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;
using System.IO;
using Tsanie.AzerothReader.Util;

namespace Tsanie.AzerothReader.Network {
    class NetBase {
        /// <summary>
        /// 开始尝试HTTP请求
        /// </summary>
        /// <param name="url">URL地址</param>
        /// <param name="requestBefore">请求发出前委托</param>
        /// <param name="asyncCallback">请求获得回应后委托</param>
        /// <param name="errCallback">异常时委托</param>
        public static void BeginConnect(string url,
            Action<HttpWebRequest> requestBefore,
            Action<RequestState> asyncCallback,
            Action<Exception> errCallback) {
            new Thread(() => {
                try {
                    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                    request.Method = "GET";
                    request.KeepAlive = true;
                    request.Accept = "*/*";
                    request.UserAgent = Config.c_UserAgent;
                    if (requestBefore != null) {
                        requestBefore(request);
                    }
                    RequestState state = new RequestState();
                    state.Request = request;
                    // 开始异步请求
                    IAsyncResult ar = request.BeginGetResponse((iar) => {
                        RequestState requestState = (RequestState)iar.AsyncState;
                        HttpWebRequest webRequest = requestState.Request;
                        try {
                            requestState.Response = (HttpWebResponse)webRequest.EndGetResponse(iar);
                            requestState.StreamResponse = requestState.Response.GetResponseStream();
                            requestState.StreamResponse.ReadTimeout = Config.Timeout;
                            if (asyncCallback != null) {
                                asyncCallback(requestState);
                            }
                            requestState.Response.Close();
                        } catch (Exception ex) {
                            LogUtil.Error(ex, errCallback);
                        }
                    }, state);
                    // 超时控制
                    ThreadPool.RegisterWaitForSingleObject(
                        ar.AsyncWaitHandle,
                        new WaitOrTimerCallback(TimeoutCallback),
                        request,
                        Config.Timeout,
                        true);
                } catch (Exception e) {
                    LogUtil.Error(e, errCallback);
                }
            }) { Name = "httpThread_" + url }.Start();
        }

        private static void TimeoutCallback(object state, bool timeOuted) {
            if (timeOuted) {
                HttpWebRequest request = state as HttpWebRequest;
                if (request != null)
                    request.Abort();
            }
        }
    }

    /// <summary>
    /// 请求类
    /// </summary>
    public class RequestState {
        const int BUFFER_SIZE = 1024;
        public byte[] Buffer { get; private set; }
        public HttpWebRequest Request { get; set; }
        public HttpWebResponse Response { get; set; }
        public Stream StreamResponse { get; set; }
        public RequestState() {
            Buffer = new byte[BUFFER_SIZE];
            Request = null;
            Response = null;
            StreamResponse = null;
        }
    }
}
